package me.ywy.apt.ormdb.sqlite.impl;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.service.notification.Condition;
import android.text.TextUtils;
import android.util.Log;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Currency;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import me.ywy.apt.ormdb.sqlite.IBaseDao;
import me.ywy.apt.ormdb.sqlite.annotation.DBField;
import me.ywy.apt.ormdb.sqlite.annotation.DBTable;

/**
 * Created by ywy on 2018-04-11.
 */
public class BaseDao<T> implements IBaseDao<T> {

    private SQLiteDatabase database;

    private Class<T> entityClass;

    private String tableName;

    private HashMap<String ,Field> cacheMap = new HashMap<>();

    private boolean isInit = false;

    public synchronized boolean init(Class<T> entity , SQLiteDatabase sqLiteDatabase ){
        if(!isInit){
            database = sqLiteDatabase;
            entityClass = entity;
            tableName = entity.getAnnotation(DBTable.class).value();
            if(!sqLiteDatabase.isOpen()){
                return false;
            }

            if(!autoCreateTable()){
                return false;
            }
            isInit = true;
        }

        initCacheMap();
        
        return isInit;
    }

    private void initCacheMap() {
        String sql = "select * from " + this.tableName + " limit 1,0";
        Cursor cursor = database.rawQuery(sql , null);
        String[] columnNames = cursor.getColumnNames();
        Field[] fields = this.entityClass.getFields();
        for (String columnName:columnNames) {

            Field resultField = null;
            for (Field field:fields) {
                if(TextUtils.equals(field.getAnnotation(DBField.class).value() , columnName)){
                    resultField = field;
                    break;
                }
            }
            if(resultField!=null){
                cacheMap.put(columnName , resultField);
            }
        }
        cursor.close();
    }

    private boolean autoCreateTable() {
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("CREATE TABLE IF NOT EXISTS ");
        stringBuffer.append(tableName + " (");
        Field[] fields = entityClass.getFields();
        for (Field field:fields) {
            Class type = field.getType();
            if(type == String.class){
                stringBuffer.append(field.getAnnotation(DBField.class).value() + " TEXT,");
            }else if(type == Double.class){
                stringBuffer.append(field.getAnnotation(DBField.class).value() + " DOUBLE,");
            }else if(type == Integer.class){
                stringBuffer.append(field.getAnnotation(DBField.class).value() + " INTEGER,");
            }else if(type == Long.class){
                stringBuffer.append(field.getAnnotation(DBField.class).value() + " BIGINT,");
            }else if(type == byte[].class){
                stringBuffer.append(field.getAnnotation(DBField.class).value() + " BLOB,");
            }else {
                continue;
            }
        }

        if(stringBuffer.charAt(stringBuffer.length()-1) == ','){
            stringBuffer.deleteCharAt(stringBuffer.length()-1);
        }

        stringBuffer.append(")");

        Log.d("orm db" ,stringBuffer.toString() );
        try {
            this.database.execSQL(stringBuffer.toString());

        } catch (SQLException e) {
            return false;
        }
        return true;
    }

    @Override
    public Long insert(T entity) {
        ContentValues contentValues = getValue(entity);

        long insertIndex = database.insert(tableName, null, contentValues);
        return insertIndex;
    }

    @Override
    public List<T> query(T where) {
        return query(where , null, null,null);
    }


    private List<T> query(T where , String orderBy , Integer startIndex , Integer limit){
        String limitString = null;
        if(startIndex != null && limit!=null){
            limitString = startIndex + "," + limit;
        }
//        Condition condition = new Condition(getContentValuse(where));
//        Cursor cursor = null;
//        List<T> result = new ArrayList<>();
//        try{
//            cursor = database.query(tableName , null ,)
//        }catch (){
//
//        }

        return null;
    }

    private ContentValues getValue(T entity) {
        ContentValues contentValues = new ContentValues();
        Iterator<Map.Entry<String, Field>> iterator = cacheMap.entrySet().iterator();
        while (iterator.hasNext()){
            Map.Entry<String, Field> fieldEntry = iterator.next();
            Field field = fieldEntry.getValue();
            String key = fieldEntry.getKey();
            field.setAccessible(true);
            try {
                Object obj = field.get(entity);
                Class type = field.getType();
                if(type == String.class){
                    contentValues.put(key ,(String)obj );
                }else if(type == Double.class){
                    contentValues.put(key ,(Double)obj );
                }else if(type == Integer.class){
                    contentValues.put(key ,(Integer)obj );
                }else if(type == Long.class){
                    contentValues.put(key ,(Long)obj );
                }else if(type == byte[].class){
                    contentValues.put(key ,(byte[])obj );
                }else {
                    continue;
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return contentValues;
    }
}
